import { Request, Response } from 'express';
import genService from '@/services/tool/gen.service';
import ApiResponse from '@/utils/api/api-response.util';
import { getLogger } from '@/utils/logger';

// 获取模块专用日志记录器
const logger = getLogger('tool');

// 给Request扩展user属性
declare module 'express' {
  interface Request {
    user?: {
      userId?: number;
      userName?: string;
      permissions?: string[];
      roles?: string[];
    };
  }
}

/**
 * 代码生成控制器
 */
class GenController {
  /**
   * 查询代码生成列表
   * @param req 请求
   * @param res 响应
   */
  public async list(req: Request, res: Response): Promise<void> {
    try {
      const { pageNum = 1, pageSize = 10, ...query } = req.query;
      
      // 转换为数字
      const pNum = parseInt(pageNum as string, 10);
      const pSize = parseInt(pageSize as string, 10);
      
      const { rows, count } = await genService.selectGenTableListPaged({
        ...query,
        pageNum: pNum,
        pageSize: pSize
      });
      
      ApiResponse.successWithTable(res, rows, count);
    } catch (err) {
      logger.error('查询代码生成列表失败', err);
      ApiResponse.error(res, '查询代码生成列表失败');
    }
  }

  /**
   * 查询数据库列表
   * @param req 请求
   * @param res 响应
   */
  public async dbList(req: Request, res: Response): Promise<void> {
    try {
      const { pageNum = 1, pageSize = 10, ...query } = req.query;
      
      // 转换为数字
      const pNum = parseInt(pageNum as string, 10);
      const pSize = parseInt(pageSize as string, 10);
      
      const { rows, count } = await genService.selectDbTableListPaged({
        ...query,
        pageNum: pNum,
        pageSize: pSize
      });
      
      ApiResponse.successWithTable(res, rows, count);
    } catch (err) {
      logger.error('查询数据库列表失败', err);
      ApiResponse.error(res, '查询数据库列表失败');
    }
  }

  /**
   * 查询表详细信息
   * @param req 请求
   * @param res 响应
   */
  public async getInfo(req: Request, res: Response): Promise<void> {
    try {
      const tableId = parseInt(req.params.tableId, 10);
      
      // 查询表信息
      const table = await genService.selectGenTableById(tableId);
      
      // 查询所有表信息（用于子表选择）
      const tables = await genService.selectGenTableAll();
      
      // 查询表字段
      const columns = await genService.selectGenTableColumnListByTableId(tableId);
      
      // 组装结果
      const result = {
        info: table,
        rows: columns,
        tables
      };
      
      ApiResponse.success(res, result);
    } catch (err) {
      logger.error('查询表详细信息失败', err);
      ApiResponse.error(res, '查询表详细信息失败');
    }
  }

  /**
   * 查询表字段列表
   * @param req 请求
   * @param res 响应
   */
  public async columnList(req: Request, res: Response): Promise<void> {
    try {
      const tableId = parseInt(req.params.tableId, 10);
      
      // 查询表字段
      const columns = await genService.selectGenTableColumnListByTableId(tableId);
      
      // 返回结果
      ApiResponse.successWithTable(res, columns, columns.length);
    } catch (err) {
      logger.error('查询表字段列表失败', err);
      ApiResponse.error(res, '查询表字段列表失败');
    }
  }

  /**
   * 导入表结构
   * @param req 请求
   * @param res 响应
   */
  public async importTable(req: Request, res: Response): Promise<void> {
    try {
      const { tables } = req.body;
      
      if (!tables) {
        ApiResponse.error(res, '请选择要导入的表');
        return;
      }
      
      // 将表名转换为数组
      const tableNames = tables.split(',');
      
      // 查询表信息
      const tableList = await genService.selectDbTableListByNames(tableNames);
      
      // 导入表结构
      await genService.importGenTable(tableList, req.user?.userName || 'admin');
      
      ApiResponse.success(res);
    } catch (err) {
      logger.error('导入表结构失败', err);
      ApiResponse.error(res, '导入表结构失败: ' + (err as Error).message);
    }
  }

  /**
   * 创建表结构
   * @param req 请求
   * @param res 响应
   */
  public async createTable(req: Request, res: Response): Promise<void> {
    try {
      const { sql } = req.body;
      
      if (!sql) {
        ApiResponse.error(res, 'SQL语句不能为空');
        return;
      }
      
      // 创建表
      const result = await genService.createTable(sql);
      
      // 返回结果
      if (result) {
        ApiResponse.success(res);
      } else {
        ApiResponse.error(res, '创建表结构失败');
      }
    } catch (err) {
      logger.error('创建表结构失败', err);
      ApiResponse.error(res, '创建表结构失败: ' + (err as Error).message);
    }
  }

  /**
   * 修改代码生成业务
   * @param req 请求
   * @param res 响应
   */
  public async update(req: Request, res: Response): Promise<void> {
    try {
      const genTable = req.body;
      
      // 校验并更新
      await genService.validateEdit(genTable);
      await genService.updateGenTable(genTable);
      
      ApiResponse.success(res);
    } catch (err) {
      logger.error('修改代码生成业务失败', err);
      ApiResponse.error(res, '修改代码生成业务失败: ' + (err as Error).message);
    }
  }

  /**
   * 删除代码生成
   * @param req 请求
   * @param res 响应
   */
  public async remove(req: Request, res: Response): Promise<void> {
    try {
      const tableIds = req.params.tableIds.split(',').map(id => parseInt(id, 10));
      
      // 删除表
      await genService.deleteGenTableByIds(tableIds);
      
      ApiResponse.success(res);
    } catch (err) {
      logger.error('删除代码生成失败', err);
      ApiResponse.error(res, '删除代码生成失败: ' + (err as Error).message);
    }
  }

  /**
   * 预览代码
   * @param req 请求
   * @param res 响应
   */
  public async preview(req: Request, res: Response): Promise<void> {
    try {
      const tableId = parseInt(req.params.tableId, 10);
      
      // 预览代码
      const codeMap = await genService.previewCode(tableId);
      
      // 转换为普通对象
      const result: Record<string, string> = {};
      codeMap.forEach((value, key) => {
        result[key] = value;
      });
      
      ApiResponse.success(res, result);
    } catch (err) {
      logger.error('预览代码失败', err);
      ApiResponse.error(res, '预览代码失败: ' + (err as Error).message);
    }
  }

  /**
   * 生成代码（下载方式）
   * @param req 请求
   * @param res 响应
   */
  public async download(req: Request, res: Response): Promise<void> {
    try {
      const tableName = req.params.tableName;
      
      // 生成代码
      const data = await genService.downloadCode([tableName]);
      
      // 设置响应头
      res.set({
        'Content-Type': 'application/octet-stream',
        'Content-Disposition': `attachment; filename=${tableName}.zip`
      });
      
      // 发送文件
      res.send(data);
    } catch (err) {
      logger.error('下载代码失败', err);
      ApiResponse.error(res, '下载代码失败: ' + (err as Error).message);
    }
  }

  /**
   * 生成代码（自定义路径）
   * @param req 请求
   * @param res 响应
   */
  public async genCode(req: Request, res: Response): Promise<void> {
    try {
      const tableName = req.params.tableName;
      
      // 生成代码
      await genService.generatorCode(tableName);
      
      ApiResponse.success(res);
    } catch (err) {
      logger.error('生成代码失败', err);
      ApiResponse.error(res, '生成代码失败: ' + (err as Error).message);
    }
  }

  /**
   * 同步数据库
   * @param req 请求
   * @param res 响应
   */
  public async syncDb(req: Request, res: Response): Promise<void> {
    try {
      const tableName = req.params.tableName;
      
      // 同步数据库
      await genService.synchDb(tableName);
      
      ApiResponse.success(res);
    } catch (err) {
      logger.error('同步数据库失败', err);
      ApiResponse.error(res, '同步数据库失败: ' + (err as Error).message);
    }
  }

  /**
   * 批量生成代码
   * @param req 请求
   * @param res 响应
   */
  public async batchGenCode(req: Request, res: Response): Promise<void> {
    try {
      const { tables } = req.query;
      
      if (!tables) {
        ApiResponse.error(res, '请选择要生成的表');
        return;
      }
      
      // 将表名转换为数组
      const tableNames = (tables as string).split(',');
      
      // 生成代码
      const data = await genService.downloadCode(tableNames);
      
      // 设置响应头
      res.set({
        'Content-Type': 'application/octet-stream',
        'Content-Disposition': 'attachment; filename=ruoyi.zip'
      });
      
      // 发送文件
      res.send(data);
    } catch (err) {
      logger.error('批量生成代码失败', err);
      ApiResponse.error(res, '批量生成代码失败: ' + (err as Error).message);
    }
  }
}

export default new GenController(); 